package node_dir

import (
	"fmt"
	"reflect"
	"runtime"
	"sanguo/cluster"
	codecs "sanguo/codec/cs"

	"github.com/golang/protobuf/proto"
	"github.com/sniperHW/kendynet"
)

//连接到服务器的session
var dirSession kendynet.StreamSession

type handler func(kendynet.StreamSession, *codecs.Message)

var gDispatcher dispatcher

type dispatcher struct {
	handlers       map[string]handler
	defaultHandler handler
}

func (this *dispatcher) SetDefaultHandler(h handler) {
	this.defaultHandler = h
}

func (this *dispatcher) Register(msg proto.Message, h handler) {
	msgName := reflect.TypeOf(msg).String()
	if nil == h {
		return
	}
	_, ok := this.handlers[msgName]
	if ok {
		return
	}

	this.handlers[msgName] = h
}

func pcall(handler_ handler, name string, session kendynet.StreamSession, msg *codecs.Message) {
	defer func() {
		if r := recover(); r != nil {
			buf := make([]byte, 65535)
			l := runtime.Stack(buf, false)
			Errorf("error on Dispatch:%s\nstack:%v,%s\n", name, r, buf[:l])
		}
	}()
	handler_(session, msg)
}

func (this *dispatcher) Dispatch(session kendynet.StreamSession, msg *codecs.Message) {
	if nil != msg {
		name := msg.GetName()
		handler, ok := this.handlers[name]
		if ok {
			//交给cluster的任务队列单线程执行
			cluster.PostTask(func() {
				pcall(handler, name, session, msg)
			})
		} else {
			cluster.PostTask(func() {
				pcall(this.defaultHandler, name, session, msg)
			})
		}
	}
}

func (this *dispatcher) OnClose(session kendynet.StreamSession, reason string) {
	u := session.GetUserData()
	if u != nil {
		u.(interface {
			OnDisConnect()
		}).OnDisConnect()
	}
	fmt.Printf("client close:%s\n", reason)
}

func (this *dispatcher) OnNewClient(session kendynet.StreamSession) {
	fmt.Printf("new client\n")
}

func RegisterHandler(msg proto.Message, h handler) {
	gDispatcher.Register(msg, h)
}

func init() {
	gDispatcher.handlers = map[string]handler{}
}
